package com.soft.bams.server;

import com.soft.bams.entity.Account;
import com.soft.bams.exception.ATMException;
import com.soft.bams.service.Bank;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author yzg
 * @desc TODO
 * @date 2025/5/28
 */
public class ServerTasker implements Runnable {
    private Socket socket;
    private Bank bank;
    private String clientIp;
    private static ConcurrentHashMap<Long,String> idIpMap = new ConcurrentHashMap<>();

    public ServerTasker(Socket socket) {
        this.socket = socket;
        this.bank = Bank.getInstance();
        this.clientIp = socket.getRemoteSocketAddress().toString();
    }


    @Override
    public void run() {
        try (
                BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
        ) {
            while (true) {
                String command = reader.readLine();
                if (command == null) {
                    break;
                }


                String[] parts = command.split("#");
                String operation = parts[0];

                switch (operation) {
                    case "login":
                        handleLogin(parts, oos);
                        break;
                    case "register":
                        handleRegister(parts, oos);
                        break;
                    case "deposit":
                        handleDeposit(parts, oos);
                        break;
                    case "withdraw":
                        handleWithdraw(parts, oos);
                        break;
                    case "transfer":
                        handleTransfer(parts, oos);
                        break;
                    case "updateCeiling":
                        handleUpdateCeiling(parts, oos);
                        break;
                    case "requestLoan":
                        handleRequestLoan(parts, oos);
                        break;
                    case "payLoan":
                        handlePayLoan(parts, oos);
                        break;
                    case "getAccount":
                        handleGetAccount(parts, oos);
                        break;
                    case "removeIdFromIdIpMap":
                        handleRemoveId(parts,oos);
                        break;
                }
            }
        } catch (IOException e) {
            System.out.println("客户端连接断开: " + e.getMessage());
        } finally {
            try {
                socket.close();
            } catch (IOException e) {
                System.out.println("关闭socket异常"+e.getMessage());
            }
        }
    }

    private void handleLogin(String[] parts, ObjectOutputStream oos) throws IOException {
        try {
            long id = Long.parseLong(parts[1]);
            String password = parts[2];

            if(idIpMap.containsKey(id)){
                oos.writeObject("该账户已在其他客户端登录，无法再次登录！");
                return;
            }
            Account account = bank.login(id, password);
            idIpMap.put(id,clientIp);
            oos.reset();
            oos.writeObject(account);
        } catch (ATMException e) {
            oos.writeObject(e.getMessage());
        }
    }

    private void handleRegister(String[] parts, ObjectOutputStream oos) throws IOException {
        try {
            Account account = bank.register(
                    parts[1], parts[2], parts[3],
                    parts[4], parts[5], Integer.parseInt(parts[6])
            );
            idIpMap.put(account.getId(),clientIp);
            oos.reset();
            oos.writeObject(account);
        } catch (ATMException e) {
            oos.writeObject(e.getMessage());
        }
    }

    private void handleDeposit(String[] parts, ObjectOutputStream oos) throws IOException {
        try {
            long id = Long.parseLong(parts[1]);
            double amount = Double.parseDouble(parts[2]);
            Account account = bank.deposit(id, amount);
            oos.reset();
            oos.writeObject(account);
        } catch (ATMException e) {
            oos.writeObject(e.getMessage());
        }
    }

    private void handleWithdraw(String[] parts, ObjectOutputStream oos) throws IOException {
        try {
            long id = Long.parseLong(parts[1]);
            String password = parts[2];
            double amount = Double.parseDouble(parts[3]);
            Account account = bank.withdraw(id, password, amount);
            oos.reset();
            oos.writeObject(account);
        } catch (ATMException e) {
            oos.writeObject(e.getMessage());
        }
    }

    private void handleTransfer(String[] parts, ObjectOutputStream oos) throws IOException {
        try {
            long from = Long.parseLong(parts[1]);
            String password = parts[2];
            long to = Long.parseLong(parts[3]);
            double amount = Double.parseDouble(parts[4]);

            boolean success = bank.transfer(from, password, to, amount);
            if (success) {
                Account account = bank.getDao().selectOne(from);
                oos.reset();
                oos.writeObject(account);
            } else {
                oos.writeObject("转账失败");
            }
        } catch (ATMException e) {
            oos.writeObject(e.getMessage());
        }
    }

    private void handleUpdateCeiling(String[] parts, ObjectOutputStream oos) throws IOException {
        try {
            long id = Long.parseLong(parts[1]);
            String password = parts[2];
            double ceiling = Double.parseDouble(parts[3]);
            Account account = bank.updateCeiling(id, password, ceiling);
            oos.reset();
            oos.writeObject(account);
        } catch (ATMException e) {
            oos.writeObject(e.getMessage());
        }
    }

    private void handleRequestLoan(String[] parts, ObjectOutputStream oos) throws IOException {
        try {
            long id = Long.parseLong(parts[1]);
            double amount = Double.parseDouble(parts[2]);
            Account account = bank.requestLoan(id, amount);
            oos.reset();
            oos.writeObject(account);
        } catch (ATMException e) {
            oos.writeObject(e.getMessage());
        }
    }

    private void handlePayLoan(String[] parts, ObjectOutputStream oos) throws IOException {
        try {
            long id = Long.parseLong(parts[1]);
            double amount = Double.parseDouble(parts[2]);
            Account account = bank.payLoan(id, amount);
            oos.reset();
            oos.writeObject(account);
        } catch (ATMException e) {
            oos.writeObject(e.getMessage());
        }
    }

    private void handleGetAccount(String[] parts, ObjectOutputStream oos) throws IOException {
        try {
            long id = Long.parseLong(parts[1]);
            Account account = bank.getDao().selectOne(id);
            oos.reset();
            oos.writeObject(account);
        } catch (Exception e) {
            oos.writeObject("获取账户信息失败");
        }
    }

    private void handleRemoveId(String[] parts, ObjectOutputStream oos) throws IOException {
        try{
            long id = Long.parseLong(parts[1]);
            idIpMap.remove(id);
            oos.reset();
            oos.writeObject("已返回,下次需重新登录");
        }catch (Exception e){
            oos.writeObject(e.getMessage());
        }
    }

    public static ConcurrentHashMap<Long,String> getAccountsIp(){
        return idIpMap;
    }
}
